#include "stdafx.h"
#include "media_play_thread.h"
#include "audio_play_channel.h"
#include "video_play_channel.h"
#include "session_mgr.h"

uint16_t& big_2_small(uint16_t &val)
{
    uint8_t _tmp_buf[2];
    uint8_t ch = 0;
    memcpy(_tmp_buf, &val, 2);
    ch = _tmp_buf[0];
    _tmp_buf[0] = _tmp_buf[1];
    _tmp_buf[1] = ch;
    memcpy(&val, _tmp_buf, 2);
    return val;
}

CMediaPlayThread::CMediaPlayThread(ILiveEvent* event_)
{
    _bplay_flag = 0;
    _pAudioChannel = NULL;
    _pVideoChannel = NULL;
    _bexit_flag = false;
#ifndef _NODES_DEBUG
    try{
        _pAudioChannel = new CAudioPlayChannel;
        _pVideoChannel = new CVideoPlayChannel(event_);
        _pAudioChannel->set_play_event_cb(boost::bind(&CMediaPlayThread::set_play_flag, this, _1));
    }catch(std::bad_alloc& e)
    {
        BOOST_ERROR << "CMediaPlayThread::CMediaPlayThread new video,audio play channel failed.errinfo:"
            << e.what();
    }
    _thread_thr = boost::thread(boost::bind(&CMediaPlayThread::execute, this));
#endif // _NODES_DEBUG
}

CMediaPlayThread::~CMediaPlayThread(void)
{
    _bexit_flag = true;
    _thread_thr.join();

    if (_pAudioChannel)
    {
        delete _pAudioChannel;
    }
    if (_pVideoChannel)
    {
        delete _pVideoChannel;
    }
}

void CMediaPlayThread::execute()
{
    int32_t width(0), height(0);
    bool flag = false;
    while(!_bexit_flag)
    {
        flag = false;
        if ( 0 == _bplay_flag.load()) //stop play
        {
            flag = false;
        }else if (1 == _bplay_flag.load())
        {
            if (_pVideoChannel && _pAudioChannel)
            {
                flag |= _pVideoChannel->play_frame(_pAudioChannel->get_audio_ts(), width, height);
            }
        }
        // do nothing
        if(!flag)
        {
#ifdef WIN32
            Sleep(1);
#else
            usleep(1000);
#endif // WIN32
        }
#ifdef _NODES_DEBUG
        Sleep(1);
#endif //_NODES_DEBUG
    }
}

//init audio and video decoder and resource
int32_t CMediaPlayThread::init(HWND hwnd_)
{
    BOOST_INFO << "media play thread init() hwnd:" << hwnd_;
    if (_pVideoChannel)
    {
        _pVideoChannel->set_video_hwnd(hwnd_);
        return 0;
    }else
    {
        BOOST_WARNING << "media play thread _pVideoChannel is null.";
        return -1;
    }
}

void CMediaPlayThread::on_host_change()
{
    flush_codec();
}

void CMediaPlayThread::on_recv_video_packet(boost::shared_ptr<NetPacket> pkt_ptr_)
{
    if (_pVideoChannel)
    {
        _pVideoChannel->put_data(pkt_ptr_);
    }
}

void CMediaPlayThread::on_recv_audio_packet(boost::shared_ptr<NetPacket> pkt_ptr_)
{
    if (_pAudioChannel)
    {
        BOOST_AUTO(itor, pkt_ptr_->audio_pkt().begin());
        while (itor != pkt_ptr_->audio_pkt().end())
        {
            _pAudioChannel->put_data(boost::shared_ptr<AudioPacket>(new AudioPacket(*itor)));
            ++itor;
        }
    }
}

void CMediaPlayThread::set_play_flag(int flag_)
{
    _bplay_flag.store(flag_);
    if (0 == flag_)
    {
        if (_pAudioChannel)
        {
            _pAudioChannel->set_play_flag(false);
        }
        if (_pVideoChannel)
        {
            _pVideoChannel->set_play_flag(false);
        }
    }else if (1 == flag_)
    {
        if (_pAudioChannel)
        {
            _pAudioChannel->set_play_flag(true);
        }
        if (_pVideoChannel)
        {
            _pVideoChannel->set_play_flag(true);
        }
    }
}

void CMediaPlayThread::flush_codec()
{
    if (_pAudioChannel)
    {
        _pAudioChannel->flush_codec();
    }
    if (_pVideoChannel)
    {
        _pVideoChannel->flush_codec();
    }
}

void CMediaPlayThread::save_bmp(const char* file_name_, const int len_)
{
    if (_pVideoChannel)
    {
        return _pVideoChannel->save_bmp(file_name_, len_);
    }
}

int32_t CMediaPlayThread::set_video_hwnd(HWND hwnd_)
{
    BOOST_INFO << "set video hwnd():" << hwnd_;
    if (_pVideoChannel)
    {
        return _pVideoChannel->set_video_hwnd(hwnd_);
    }else
    {
        BOOST_ERROR << "video channel is null.";
    }
    return -1;
}

